home *** CD-ROM | disk | FTP | other *** search
/ Fritz: All Fritz / All Fritz.zip / All Fritz / FILES / PROGNG_C / TPTC17GS.LZH / TPCDECL.INC < prev    next >
Text File  |  1988-05-03  |  19KB  |  819 lines

  1.  
  2. (*
  3.  * TPTC - Turbo Pascal to C translator
  4.  *
  5.  * (C) 1988 Samuel H. Smith (rev. 13-Feb-88)
  6.  *
  7.  *)
  8.  
  9. function exprlimit(var ex: string): integer;
  10.    {determine limit value for given static expression}
  11. var
  12.    sym:     symptr;
  13. begin
  14.    if isnumber(ex) then
  15.       sym := nil
  16.    else
  17.       sym := locatesym(ex);
  18.  
  19.    if (sym <> nil) and (sym^.limit > 0) then
  20.    begin
  21.       exprlimit := sym^.limit;
  22.       exit;
  23.    end;
  24.  
  25.    exprlimit := htoi(ex);
  26. end;
  27.  
  28.  
  29. procedure initialize_global(id: string80; exp: string);
  30.    {generate code to initialize a global variable at runtime}
  31. begin
  32.    if length(exp) = 0 then
  33.       exit;
  34.  
  35. {writeln('[init global, id=',id,' exp=',exp,']');}
  36.  
  37.    if ((unitlevel > 0) and (not in_interface)) or (pos('(',exp)=0) then
  38.    begin
  39.       puts(' = '+exp);
  40.       exit;
  41.    end;
  42.  
  43.    {enter into global initializer table}
  44.    addinit(id+' = '+exp);
  45. end;
  46.  
  47.  
  48.  
  49. (********************************************************************)
  50. (*
  51.  * process pascal data type specifications
  52.  *
  53.  *)
  54.  
  55. function psimpletype: string80;
  56.    {parse a simple (single keyword and predefined) type; returns the
  57.     translated type specification; sets the current data type}
  58. begin
  59.    if debug_parse then write(' <simpletype>');
  60.  
  61.    if cursym = nil then
  62.    begin
  63.      if debug then
  64.         warning('Unknown simple type');
  65.    end
  66.    else
  67.  
  68.    begin
  69.       ltok := cursym^.repid;
  70.       if tok[1] = '^' then
  71.          ltok := '^' + ltok;
  72.       while cursym^.symtype = ss_subtype do
  73.          cursym := cursym^.parent;
  74.       curparent := cursym;
  75.    end;
  76.  
  77. (*
  78. if debug then
  79. writeln(' psimtype: tok=',ltok,
  80.               ' ty=',typename[cursym^.symtype],
  81.               ' par=',cursym^.parent^.repid);
  82. *)
  83.    psimpletype := ltok;
  84.    gettok;
  85. end;
  86.  
  87.  
  88. (********************************************************************)
  89. procedure pdatatype(stoclass: anystring;
  90.                     var vars: paramlist;
  91.                     prefix:   anystring;
  92.                     suffix:   anystring;
  93.                     addsemi:  boolean);
  94.    {parse any full data type specification;  input is a list of variables
  95.     to be declared with this data type; stoclass is a storage class prefix
  96.     (usually 'static ', '', 'typedef ', or 'extern '.  prefix and suffix
  97.     are variable name modifiers used in pointer and subscript translations;
  98.     recursive for complex data types}
  99.  
  100. const
  101.    forward_typedef: anystring = '';
  102.    forward_undef:   anystring = '';
  103.  
  104. var
  105.    i:       integer;
  106.    ts:      anystring;
  107.    ex:      anystring;
  108.    sym:     symptr;
  109.    nbase:   integer;
  110.    ntype:   symtypes;
  111.  
  112.  
  113.    procedure pvarlist(typemark: string80);
  114.    var
  115.       i:    integer;
  116.       pcnt: integer;
  117.  
  118.    begin
  119.       ts := '';
  120.       pcnt := -1;
  121.  
  122. (**
  123. if debug then
  124. writeln(' pvl nbase=',nbase,' tok=',ltok,' ty=',typename[ntype]);
  125. **)
  126.       if tok = 'ABSOLUTE' then
  127.       begin
  128.          if debug_parse then write(' <abs>');
  129.  
  130.          gettok;        {consume the ABSOLUTE}
  131.          ts := pexpr;   {get the absolute lvalue}
  132.  
  133.          if tok[1] = ':' then    {absolute addressing}
  134.          begin
  135.             gettok;
  136.             ts := 'MK_FP('+ts+','+pexpr+')';
  137.          end
  138.          else                 {variable aliasing}
  139.          begin
  140.             if ts[1] = '*' then
  141.                ts := copy(ts,2,255)
  142.             else
  143.                ts := '&' + ts;
  144.          end;
  145.          
  146.          {determine proper pointer type}
  147.          if (ntype <> ss_pointer) or (prefix = '*') then
  148.          begin
  149.             {force automatic pointer dereference in expressions}
  150.             if (length(suffix) = 0) and (length(prefix) = 0) then
  151.                pcnt := -2;
  152.             typemark := typemark + ' *';
  153.          end;
  154.  
  155.          {typecase pointers}
  156.          ts := typecast(typemark,ts);
  157.       end;
  158.  
  159.       if length(typemark) > 0 then
  160.          puts(stoclass+ljust(typemark,identlen));
  161.  
  162.  
  163.       if tok = 'SYMTYPE' then
  164.       begin
  165.          if debug_parse then write(' <builtin>');
  166.          gettok;
  167.          ntype := first_symtype;
  168.          while (ntype < last_symtype) and (tok <> typename[ntype]) do
  169.             inc(ntype);
  170.          gettok;
  171.       end;
  172.  
  173.       for i := 1 to vars.n do
  174.       begin
  175.          newsym(vars.id[i],ntype,pcnt,withlevel,curlimit,nbase,curparent);
  176.          if length(ts) = 0 then
  177.             puts(prefix+vars.id[i]+suffix)
  178.          else
  179.             puts(vars.id[i]);
  180.          initialize_global(vars.id[i],ts);
  181.          if i < vars.n then
  182.             puts(', ');
  183.       end;
  184.  
  185.       if curparent = nil then
  186.          curparent := cursym;
  187.    end;
  188.  
  189.  
  190.    procedure parray;
  191.    begin
  192.       if debug_parse then write(' <array>');
  193.  
  194.       gettok;     {consume the ARRAY}
  195.  
  196.       repeat
  197.          gettok;        {consume the [ or ,}
  198.  
  199.          ts := pexpr;   {consume the lower subscript expression}
  200.          nbase := exprlimit(ts);
  201.  
  202.          if tok = '..' then
  203.          begin
  204.             gettok;   {consume the ..}
  205.             ex := ts;
  206.             ts := pexpr;
  207.             ex := ' /* ' + ex + '..' + ts + ' */ ';
  208.  
  209.             i := exprlimit(ts);
  210.             if i <> 0 then
  211.                ts := itoa(i);
  212.             subtract_base(ts,nbase-1);
  213.             if isnumber(ts) then
  214.                ts := ex + ts;
  215.          end
  216.          else
  217.  
  218.          begin    {subscript by typename - look up type range}
  219.             sym := locatesym(ts);
  220.             if sym <> nil then
  221.             begin
  222.                nbase := sym^.base;
  223.                if (sym^.limit > 0) and (sym^.symtype <> ss_const) then
  224.                   ts := ' /* ' + ts + ' */ ' + itoa(sym^.limit-nbase+1);
  225.             end;
  226.          end;
  227.    
  228.          suffix := suffix + '[' + ts + ']'; 
  229.  
  230.       until tok[1] <> ',';
  231.       
  232.       gettok;     {consume the ]}
  233.       gettok;     {consume the OF}
  234.  
  235.       ntype := ss_array;
  236. (*
  237. if debug then
  238. writeln(' array ts=',ts,' nbase=',nbase,' tok=',ltok);
  239. *)
  240.    end;
  241.  
  242.  
  243.    procedure pstring;
  244.    begin
  245.       if debug_parse then write(' <string>');
  246.  
  247.       gettok;     {consume the STRING}
  248.  
  249.       if tok[1] = '[' then
  250.       begin
  251.          gettok;     {consume the [}
  252.  
  253.          ts := pexpr;
  254.          subtract_base(ts,-1);            {increment string size by one}
  255.          suffix := suffix + '[' + ts + ']'; 
  256.          
  257.          gettok;     {consume the ]}
  258.       end
  259.       else
  260.          suffix := suffix + '[STRSIZ]';
  261.  
  262.       curparent := stringsym;
  263.       nbase := 1;
  264.       pvarlist('char');
  265.    end;
  266.  
  267.  
  268.    procedure ptext;
  269.    begin
  270.       if debug_parse then write(' <text>');
  271.  
  272.       gettok;     {consume the TEXT}
  273.  
  274.       if tok[1] = '[' then
  275.       begin
  276.          gettok;     {consume the [}
  277.          ts := pexpr;
  278.          gettok;     {consume the ]}
  279.       end;
  280.  
  281.       curparent := textsym;
  282.       pvarlist('text');
  283.    end;
  284.  
  285.  
  286.    procedure pfile;
  287.    begin
  288.       if debug_parse then write(' <file>');
  289.  
  290.       gettok;     {consume the FILE}
  291.  
  292.       if tok = 'OF' then
  293.       begin
  294.          gettok;     {consume the OF}
  295.          ts := tok;
  296.          gettok;     {consume the recordtype}
  297.          ts := ' /* file of '+ts+' */';
  298.       end
  299.       else
  300.          ts := ' /* untyped file */';
  301.  
  302.       curparent := textsym;
  303.       pvarlist('int'+ts);
  304.    end;
  305.  
  306.  
  307.    procedure pset;
  308.    begin
  309.       if debug_parse then write(' <set>');
  310.  
  311.       gettok;     {consume the SET}
  312.       gettok;     {consume the OF}
  313.  
  314.       ts := ' /* ';
  315.       if toktype = identifier then
  316.          ts := ts + usetok
  317.       else
  318.  
  319.       if tok = '(' then
  320.       begin
  321.          repeat
  322.             ts := ts + usetok
  323.          until (tok[1] = ')') or recovery;
  324.          ts := ts + usetok;
  325.       end
  326.       else
  327.          ts := ts + psetof;
  328.       ts := ts + ' */';
  329.  
  330.       ntype := ss_struct;
  331.       curparent := nil;
  332.  
  333.       pvarlist('setrec'+ts);
  334.    end;
  335.  
  336.  
  337.    procedure pvariant;
  338.    begin
  339.       if debug_parse then write(' <variant>');
  340.  
  341.       gettok;     {consume the CASE}
  342.  
  343.       ex := ltok;
  344.       gettok;     {consume the selector identifier}
  345.  
  346.       if tok[1] = ':' then
  347.       begin
  348.          gettok;     {consume the :}
  349.          ts := psimpletype;
  350.          newsym(ex,ss_scalar,-1,1,0,0,curparent);
  351.          
  352.          puts(ts+' '+ex+ ';  /* Selector */');
  353.       end
  354.       else
  355.          puts(' /* Selector is '+ex+' */');
  356.  
  357.       gettok;
  358.       puts('union { ');
  359.       newline;
  360.  
  361.       while (tok <> '}') and not recovery do
  362.       begin
  363.          ts := pexpr;      {parse the selector constant}
  364.          while tok[1] = ',' do
  365.          begin
  366.             gettok;
  367.             ts := pexpr;
  368.          end;
  369.  
  370.          gettok;    {consume the :}
  371.  
  372.          puts(' struct {  ');
  373.  
  374.          if (ts[1] = '"') or (ts[1] = '''') then
  375.            ts := ts[2];
  376.          ts := 's' + ts;
  377.          decl_prefix := 'v.'+ts+'.';
  378.          pvar;
  379.          decl_prefix := '';
  380.          
  381.          gettok;    {consume the ')'}
  382.  
  383.          puts(' } '+ts+';');
  384.  
  385.          {arrange for reference translation}
  386.          newsym(ts,ss_struct,-1,0,0,0,nil);
  387.          cursym^.repid := ts;
  388.          usesemi;
  389.       end;
  390.  
  391.       puts(' } v;');
  392.       newline;
  393.    end;
  394.  
  395.  
  396.    procedure precord;
  397.    begin
  398.       if debug_parse then write(' <record>');
  399.  
  400.       puts(stoclass+'struct '+vars.id[1]+' { ');
  401.  
  402.       inc(withlevel);
  403.       pvar;     {process each record member}
  404.  
  405.       if tok = 'CASE' then    {process the variant part, if any}
  406.          pvariant;
  407.  
  408.       puttok;   {output the closing brace}
  409.       gettok;   {and consume it}
  410.  
  411.       dec(withlevel);
  412.  
  413.       ntype := ss_struct;
  414.       curparent := nil;
  415.       pvarlist(''); {output any variables of this record type}
  416.  
  417.       {convert a #define into a typedef in case of a forward pointer decl}
  418.       if length(forward_typedef) > 0 then
  419.       begin
  420.          puts(';'); 
  421.          newline;
  422.          puts(forward_undef); 
  423.          newline;
  424.          puts(forward_typedef);
  425.          forward_typedef := '';
  426.       end;
  427.    end;
  428.  
  429.  
  430.    procedure penum;
  431.    var
  432.       members: integer;
  433.  
  434.    begin
  435.       if debug_parse then write(' <enum>');
  436.  
  437.       puts(stoclass+'enum { ');
  438.  
  439.       gettok;
  440.       members := 0;
  441.       repeat
  442.          puts(ltok);
  443.          if toktype = identifier then
  444.          begin
  445.             newsym(ltok,ss_const,-1,0,members,0,intsym);
  446.             inc(members);
  447.          end;
  448.          gettok;
  449.       until (tok[1] = ')') or recovery;
  450.  
  451.       puts(' } ');
  452.       gettok;   {consume the )}
  453.  
  454.       curlimit := members-1;
  455.       curparent := intsym;
  456.       nbase := 0;
  457.       pvarlist('');
  458.    end;
  459.  
  460.  
  461.    procedure pintrange;
  462.    begin
  463.       if debug_parse then write(' <int.range>');
  464.  
  465.       ex := pexpr;   {consume the lower limit expression}
  466.       nbase := htoi(ex);
  467.       
  468.       if tok <> '..' then
  469.       begin
  470.          syntax('".." expected');
  471.          exit;
  472.       end;
  473.       
  474.       gettok;        {consume the ..}
  475.       ts := pexpr;   {consume the number}
  476.  
  477.       curlimit := exprlimit(ts);
  478.       curparent := intsym;
  479.  
  480.       pvarlist('int /* '+ex+'..'+ts+' */');
  481.    end;
  482.  
  483.  
  484.    procedure pcharrange;
  485.    begin
  486.       if debug_parse then write(' <char.range>');
  487.  
  488.       ex := pexpr;   {consume the lower limit expression}
  489.       nbase := ord(ex[2]);
  490.  
  491.       if tok <> '..' then
  492.       begin
  493.          syntax('".." expected');
  494.          exit;
  495.       end;
  496.  
  497.       gettok;        {consume the ..}
  498.       ts := pexpr;   {consume the number}
  499.  
  500.       curlimit := exprlimit(ts);
  501.       curparent := charsym;
  502.  
  503.       pvarlist('char /* '+ex+'..'+ts+' */');
  504.    end;
  505.  
  506.  
  507.    procedure psimple;
  508.    begin
  509.       ex := psimpletype;
  510.       if ntype <> ss_array then
  511.          nbase := curparent^.base; {??}
  512.  
  513.       if tok =  '..' then
  514.       begin
  515.          if debug_parse then write(' <range>');
  516.          gettok;        {consume the ..}
  517.          ts := pexpr;   {consume the number}
  518.  
  519.          nbase := exprlimit(ex);
  520.          curlimit := exprlimit(ts);
  521.          curparent := intsym;
  522.  
  523.          pvarlist('int /* '+ex+'..'+ts+' */');
  524.          exit;
  525.       end;
  526.  
  527.       {pointer to simpletype?}      
  528.       i := pos('^',ex);
  529.       if i <> 0 then
  530.       begin
  531.          if debug_parse then write(' <pointer>');
  532.  
  533.          delete(ex,i,1);
  534.          prefix := '*';
  535.          ntype := ss_pointer;
  536.       end;
  537.    
  538.       sym := locatesym(ex);
  539.  
  540.       {potential forward pointer reference?}
  541.       if (stoclass = 'typedef ') and (vars.n = 1) and 
  542.          (prefix = '*') and (sym = nil) then
  543.       begin
  544.          if debug_parse then write(' <forward>');
  545.  
  546.          newsym(vars.id[1],ntype,-1,0,curlimit,0,nil);
  547.          puts(ljust('#define '+vars.id[1],identlen)+'struct '+ex+' *');
  548.          forward_undef := '#undef '+vars.id[1];
  549.          forward_typedef := 'typedef struct '+ex+' *'+vars.id[1];
  550.          addsemi := false;
  551.       end
  552.       else
  553.  
  554.       {ordinary simple types}
  555.       begin
  556.          if debug_parse then write(' <simple>');
  557.          pvarlist(ex);
  558.       end;
  559.    end;
  560.  
  561. begin   {pdatatype}
  562.  
  563.    curlimit := 0;
  564.    nbase := 0;
  565.    if stoclass = 'typedef ' then
  566.       ntype := ss_subtype
  567.    else
  568.       ntype := ss_scalar;
  569.    curparent := voidsym;
  570.  
  571.    if tok = 'EXTERNAL' then
  572.    begin
  573.       gettok;     {consume the EXTERNAL}
  574.       stoclass := 'extern '+stoclass;
  575.    end;
  576.    
  577.    if tok = 'PACKED' then
  578.       gettok;
  579.    while tok = 'ARRAY' do
  580.       parray;
  581.    if tok = 'PACKED' then
  582.       gettok;
  583.  
  584.    if tok = 'STRING'        then pstring
  585.    else if tok = 'TEXT'     then ptext
  586.    else if tok = 'FILE'     then pfile
  587.    else if tok = 'SET'      then pset
  588.    else if tok = '('        then penum
  589.    else if tok = 'RECORD'   then precord
  590.    else if toktype = number then pintrange
  591.    else if toktype = chars  then pcharrange
  592.    else psimple;
  593.  
  594.    if addsemi then
  595.       puts(';');
  596.    puts(' ');
  597.  
  598.    usesemi;
  599. end;
  600.  
  601.  
  602. (********************************************************************)
  603. (*
  604.  * declaration keyword processors
  605.  *   const, type, var, label
  606.  *
  607.  * all enter with tok=section type
  608.  * exit with tok=new section or begin or proc or func
  609.  *
  610.  *)
  611.  
  612. procedure pconst;
  613.    {parse and translate a constant section}
  614. var
  615.    vars:    paramlist;
  616.    parlev:  integer;
  617.    exp:     string;
  618.    term:    string;
  619.    complex: boolean;
  620.  
  621.    procedure check_complex;
  622.    begin
  623.       if not complex then
  624.          puts(' = ');
  625.       puts(exp);
  626.       exp := '';
  627.       complex := true;
  628.    end;
  629.    
  630. begin
  631.    if debug_parse then write(' <const>');
  632.  
  633.    gettok;
  634.  
  635.    while (toktype <> keyword) and not recovery do
  636.    begin
  637.       nospace := false;
  638.       vars.n := 1;
  639.       vars.id[1] := ltok;
  640.       complex := false;
  641.  
  642.       curparent := cursym;
  643.       gettok;    {consume the id}
  644.  
  645.       if tok[1] = '=' then     {untyped constant}
  646.       begin
  647.          if debug_parse then write(' <untyped.const>');
  648.  
  649.          gettok;   {consume the =}
  650.  
  651.          exp := pexpr;
  652.          if isnumber(exp) then
  653.             curlimit := htoi(exp);
  654.          {if (cexprsym^.symtype = ss_pointer) then
  655.             cexprsym := cexprsym^.parent;}
  656.          newsym(vars.id[1],ss_const,-1,0,curlimit,0,cexprsym);
  657.  
  658.          case exprtype of
  659.             'd','D','b','c':
  660.                puts('enum { '+ljust(vars.id[1],identlen)+'= '+exp+' };');
  661.             's':
  662.                puts('#define '+ljust(vars.id[1],identlen)+' '+exp);
  663.             else
  664.                puts('const '+cexprsym^.repid+ljust(vars.id[1],identlen)+'= '+exp+';');
  665.          end;
  666.  
  667.          usesemi;
  668.       end
  669.       else
  670.  
  671.       begin               {typed constants}
  672.          if debug_parse then write(' <typed.const>');
  673.  
  674.          gettok;   {consume the :}
  675.  
  676.          pdatatype('',vars,'','',false);
  677.          puts(ljust('',identlen-length(vars.id[1])-1));
  678.  
  679.          gettok;   {consume the =}
  680.          parlev := 0;
  681.          exp := '';
  682.  
  683.          repeat
  684.             if tok[1] = '[' then
  685.             begin
  686.                gettok;     {consume [}
  687.                exp := exp + psetof;
  688.                gettok;     {consume ]}
  689.             end
  690.             else
  691.             
  692.             if tok[1] = '(' then
  693.             begin
  694.                inc(parlev);
  695.                exp := exp + '{';
  696.                gettok;
  697.             end
  698.             else
  699.  
  700.             if tok[1] = ')' then
  701.             begin
  702.                dec(parlev);
  703.                exp := exp + '}';
  704.                gettok;
  705.             end
  706.             else
  707.  
  708.             if tok[1] = ',' then
  709.             begin
  710.                exp := exp + ',';
  711.                check_complex;
  712.                gettok;
  713.             end
  714.             else
  715.  
  716.             if (parlev > 0) and (tok[1] = ';') then
  717.             begin
  718.                exp := exp + ',';
  719.                check_complex;
  720.                gettok;
  721.             end
  722.             else
  723.  
  724.             if tok[1] <> ';' then
  725.             begin
  726.                term := pexpr;
  727.                if tok[1] = ':' then
  728.                   gettok   {discard 'member-identifier :'}
  729.                else
  730.                   exp := exp + term;
  731.             end;
  732.  
  733.          until ((parlev = 0) and (tok[1] = ';')) or recovery;
  734.  
  735.          if complex then
  736.          begin
  737.             puts(exp);
  738.             exp := '';
  739.          end;
  740.          
  741.          initialize_global(vars.id[1],exp);
  742.          puts(';');
  743.          gettok;
  744.       end;
  745.    end;
  746. end;
  747.  
  748.  
  749. (********************************************************************)
  750. procedure ptype;
  751.    {parse and translate a type section}
  752. var
  753.    vars: paramlist;
  754.  
  755. begin
  756.    if debug_parse then write(' <type>');
  757.  
  758.    gettok;
  759.  
  760.    while (toktype <> keyword) do
  761.    begin
  762.       vars.n := 1;
  763.       vars.id[1] := usetok;
  764.       gettok;                {consume the =}
  765.  
  766.       nospace := false;
  767.       pdatatype('typedef ',vars,'','',true);
  768.    end;
  769.  
  770. end;
  771.  
  772.  
  773. (********************************************************************)
  774. procedure pvar;
  775.    {parse and translate a variable section}
  776. var
  777.    vars:  paramlist;
  778.    sto:   string20;
  779. begin
  780.    if debug_parse then write(' <var>');
  781.  
  782.    if in_interface and (withlevel = 0) then
  783.       sto := 'extern '
  784.    else
  785.       sto := '';
  786.  
  787.    vars.n := 0;
  788.    gettok;
  789.  
  790.    while (toktype <> keyword) and (tok[1] <> '}') and (tok[1] <> ')') do
  791.    begin
  792.       nospace := true;
  793.  
  794.       repeat
  795.          if tok[1] = ',' then
  796.             gettok;
  797.  
  798.          inc(vars.n);
  799.          if vars.n > maxparam then
  800.             fatal('Too many identifiers (pvar)');
  801.          vars.id[vars.n] := ltok;
  802.          gettok;
  803.       until tok[1] <> ',';
  804.  
  805.       if tok[1] <> ':' then       
  806.       begin
  807.          syntax('":" expected');
  808.          exit;
  809.       end;
  810.          
  811.       gettok;   {consume the :}
  812.       nospace := false;
  813.       pdatatype(sto,vars,'','',true);
  814.       vars.n := 0;
  815.    end;
  816. end;
  817.  
  818.  
  819.